home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Megahits 5
/
Megahits 5 (1994)(GTI - Rhein-Main-Soft)(DE)(Disc 2 of 2)[!].iso
/
archive
/
print
/
ll.lha
/
manual.txt
< prev
next >
Wrap
Text File
|
1994-02-16
|
26KB
|
1,484 lines
LL v2.0
A Label Language Compiler
© 1994 Kevin A. McHugh
DISCLAIMER
THIS SOFTWARE IS PROVIDED "AS IS" AND NO WARRANTIES ARE OFFERED
NOR WILL ANY LIABILITY BE ASSUMED DUE TO ITS USE. THIS SOFTWARE
HAS BEEN THOROUGHLY TESTED OVER MONTHS AND HAS BEEN FOUND
TO BE DEFECT-FREE.
THIS SOFTWARE IS FREE OF CHARGE "FREEWARE." NO MONEY SHALL BE
CHARGED FOR THIS PROGRAM EXCEPT DISTRIBUTION/COPYING COSTS
WHICH HAVE NOT TO EXCEED $5 US. THE LL PACKAGE MAY BE DISTRIB
UTED IN ANY FORM, ELECTRONICALLY OR OTHERWISE AS LONG AS THE
FULL CONTENTS REMAIN IN THE ARCHIVE.
THE SOURCE CODE IS NOT INCLUDED BUT MAY BE OBTAINED FROM THE
AUTHOR.
Kevin A. McHugh
4671 Mebane Rogers Road.
Mebane, NC 27302
U.S.A.
Internet: mchugh@hamlet.uncg.edu
FidoNet: sysop@1:3644/13.0
BBS: (919) 563-0183
Introduction
What is LL? LL is a compiler that takes your source code and produces formatted
output based on instructions in the code. I wrote this program because every month
I distribute postcards for the local Amiga users group and had not found a flexible
utility for making both the addresses on the front and the text on the back of the
card.
I had wanted to use my compiler skills for a while so they wouldn't get rusty and
this is why I chose a Shell based interface over the standard GUI of the Amiga. Due
to the fact this is a Shell interface it can easily be ported to any platform that will
compile ANSI-C.
LL reads source files that are written in a language I call "L." It reads instructions
and blocks of data and then produces a final result based on your code. L is a very
simple language and even if you don't program it will not be hard for you to use.
Before you use the program please read and acknowledge the disclaimer on the
previous page. For program support and information I can be reached at the re
sources shown above. Internet mail is preferred.
The Language "L"
L is a very simple and easy language. It's format is modelled after the C language.
Unlike a true language it doesn't offer input/output or user interaction. It is more
closely related to other text compilers such as the Unix "troff" etc..
The language is defined as follows:
1. Variables
2. Printer Commands
3. The Data
4. Data Functions
5. Printer Commands
6. Functions
Comments can be used anywhere throughout the source file. L accepts the standard
C comments and the newer C++ comments. A C comment is a block of text that
starts with /* ends with */ and has anything in-between. The newer C++ comments
are started with // and terminate at the end of the same line. Note: You cannot
nest comments.
/*
** This Is A C Comment
*/
// This Is A C++ Comment ;-)
L is a case-insensitive language, basically this means that if L sees the words
PRINT, print, Print, PrInT or any combination it interprets them all as the print
command. Normally we type everything in lower or UPPER case for comprehen
sion. Any data enclosed in a data block is case sensitive so you control exactly
what is being output.
Generally speaking, all white space is ignored unless relevant. This means that you
can format your L code however makes you feel comfortable, the program is smart
enough to know when to skip white space and when to keep it. By definition, white
space is any character which you cannot regularly see. (carriage returns, linefeeds,
spaces, tabs etc...)
1. Variables
L has pre-defined variables for formatting your text. You can use them however you
like and in whatever order you like as long as they precede what you want to print.
All variables are entered in the following format:
#define variable_name = value ;
Where variable_name is one of the pre-defined variables and value is a valid value.
The equal sign "=" is optional but the compiler will produce a warning if it is omit
ted.
The variables are as follows:
device
height
width
space
indent
header
footer
postage
eol
DEVICE
Example: #define device = prt:;
Default: l.out
The device variable tells the compiler where to send the output it generates. Out
put can go to a text file or a device such as a printer. If you choose the device to be
prt: (the standard AmigaDOS printer device) then all printer information from Pre
ferences will be used. If you will be using the Postnet bar code feature of LL then in
order for your output to come out correctly you will need to select the PAR: device
as your final output destination. Postnet will be discussed later in the manual.
Generally it is best to send output to a temporary file until you have everything cor
rect for final printing. This can be done by specifying a filename instead of a device
like follows:
#define device = test.output;
#define device = "address list";
Note that you need to quote the filename if it contains spaces. If you enter multiple
device entries then only the last one will be used.
HEIGHT
Example: #define height = 24;
Default: 10
The height variable sets the height of the output form so that correct paper han
dling will be produced. The height is in printer lines. If you know the height in
inches you can easily derive the height in lines:
lines = height_in_inches * lines_per_inch
Your printer manual and Workbench preferences will show you how many lines per
inch your printer is set for. Note that height must be an integer and cannot contain
a floating point value.
WIDTH
Example: #define width = 60;
Default: 40
The width variable specifies the width of the output form. The width is measured in
characters. A standard letter sized 8.5" x 11" page prints 80 characters across so
you can estimate approximately 10 characters per inch (CPI). Your CPI rate will be
found in your printers manual and information on how to change it will also be
available. Note that width must be an integer.
SPACE
Example: #define space = 10;
Default: 2
The space variable indicates the number of lines to feed the paper before printing
should commence. Like the height, space is measured in printer lines. For obvious
reasons, space should be less than the page height. Note space must also be an
integer.
INDENT
Example: #define indent = 7;
Default: 5
The indent variable is the number of characters to move the printhead in before
printing the data. The size of a character can be calculated by refering to your
printers current CPI setting.
HEADER
Example: #define header = "This Is A Header";
Default: None
The header variable is a string of characters that will be printed before each data
block. This is handy for printing dates and times etc... The header may be enclosed
in quotes but it is not absolutely required but highly recommended.
Headers can also use imbedded codes to produce run-time output for example the
date or the time. The imbedded codes are similar to the codes used in the C lan
guage and are listed below:
Escape Codes:
\\ Backslash \
\" Quote Character "
\d Date 01/03/94
\e Escape ASCII 27
\i Indent 1 Indent's Spaces
\n Newline ASCII 14
\r Carrage Return ASCII 13
\t Time 18:06:51
\x Hex Time 2 2d2c0347
1 The indent code will indent the following text by the number of spaces de
fined by the indent variable.
2 The Hex Time code represents the number of seconds passed since January 1,
1970 to now. It is expressed in hexadecimal notation.
Here are some examples of text using embedded codes followed by the actual output
after compilation.
#define header = "Mailed: \d\r\nAt: \t";
Mailed: 02/11/94
At: 19:25:01
#define header = "Code ***\x***";
Code ***2d2c3561***
The possibilities are endless and can add extra style to your mailings without hav
ing to do extra work. Note if no header is declared then none will be printed.
FOOTER
Example: #define footer = "This Is A Footer";
Default: None
The footer serves the exact same purpose of the header except that it is printed
proceding every data block instead of before. The footer variable also excepts a
string of characters and can contain embedded escape codes.
#define footer = "------------------------------------";
The above will simply print a dotted line after each data block. Note if no footer is
declared then none will be printed.
POSTAGE
Example: #define postage = 0.19;
Default: 0.00
The postage variable is only used if you choose to have LL make a summary of your
mailings at the end of each session. If you use the report() function in your program
then the total cost of the mailing session will be computed using the above number
as the cost for mailing one data block. The value entered is in dollars and cents and
can be integer or floating point.
#define postage = .01 // 1 cent for each mailing.
#define postage = .1 // 10 cents for each mailing.
#define postage = 1; // $1 for each mailing.
#define postage = 1.00; // $1 for each mailing.
If the postage variable is not declared and a cost summary is requested then the
compiler will assume there is no mailing cost and substitute a value of 0.00 for the
postage variable.
EOL
Example: #define eol = crlf;
Default: lf
The EOL variable stands for "End Of Line." It tells the compiler how to handle a
situation when it reaches the end of a line and needs to feed the paper. There are
two options you can use for the eol variable:
lf
crlf
LF means that when you reach the end of a line simply send the linefeed character
to the printer and continue with printing. This will work for most printers.
CRLF means that when the end of line is reached make the printer issue a carriage
return and then do a linefeed.
2. Printer Commands
L has a built in command called PRINTER. It's sole purpose is to send commands
to the printer. The command is entered in the following way:
printer " character_string " ;
Where character_string is a piece of text separated by quotation marks. The string
can contain embedded escape codes (see Section 1 "HEADER") and is generally used
to setup your printer.
With the embedded escape codes you have the ability to send actual setup codes to
your specific printer using the \E escape code.
printer "\eq1";
printer "\eq0";
The above example will turn on the Shadow font on my Epson 5000 printer while
the second line turns it back off. So you can easily see that custom printing is easily
accessible with LL.
The printer command can be issued as many times as needed but can only appear
before and after the data block. This was designed for setting up and then resetting
your printer's defaults.
3. The Data (Data Block)
The main data block follows both the #defines and the printer commands. This is
where your data to be printed goes. In order for the compiler to know about the
data we use the key word address, after all LL was written for making address la
bels. Following the word address is the data to be printed enclosed in curly braces.
Here is the template:
address ( zip_code ) { data } function ;
The function is completely optional and the available functions will be covered in
section 4.
The zip_code which is entered between the parenthesis is optional. If a zip code is
entered then the LL compiler will print the United States Postnet Bar Code for the
corresponding zip code to the output device. Postnet will be covered in the next sec
tion (3.1).
The data is unlimited in size. The data block is allocated dynamically as the pro
gram in run so your printing area is only limited by your available memory. If you
run out of memory during a compile then the compiler will issue a fatal warning
and exit gracefully. Here is an example:
address (27302)
{
Kevin McHugh
4671 Mebane Rogers Road
Mebane, NC 27302
} ;
Note that the address block doesn't have to be on one line. Because the compiler is
intelligent it knows what we mean so we can make the source code more readable
for ourselves. When formatting the data block we position the text just as we want
it to appear in print. White space before and after any text is omitted and spacing
is decided upon your earlier #defines so neatness is not required as LL will take
care of that for you.
You may specify as many data entries as you wish and in as many different ways as
you wish, for example:
address ( )
{
This is my first data block :-)
};
address ( ) { This is my second };
address
( )
{ This is my third and
final one for now :) };
So you can see that your style is truly your own. I tend to format mine like I do my
C code so you can line up the braces vertically but that is entirely preference.
3.1. The PostNet Bar Code Standard
The United States Post Office uses a bar code on their mailing systems for faster
processing and therefore quicker delivery. This bar code is a coded representation
of the addressees zip code. The zip code may be either a standard Zip or the newer
more accurate Zip+4 code.
Whichever you choose you have the option of letting LL print the bar code for you.
At the release date, version 2.0 only supports bar code printing to Epson and IBM
compatible graphics printers. Future versions will fully support the Amiga Prefer
ences graphics standard so any Preference printer may be used.
LL accesses the graphics modes on the printers directly therefore if you choose your
output device as PRT: then the graphics characters will be interpreted by Prefer
ences and you will have a row of strange looking characters instead of the bar code.
To correct this problem we simply bypass the PRT: device and go straight to the
parallel device PAR:. This eliminates any interaction on the behalf of Preferences
and the bar codes will be printed correctly.
NOTE: PostNet Bar Codes will only be printed correctly if using the PAR: device.
Here is a bar code using the PRT: device.
¤¤¤¤¤¤¥¥¥¥¥¥yyyyy¤¤¤¤¤¤¤¤
And here is one using PAR:
All LL needs to know in order to print a Postnet Bar Code is the addressees zip
code. The way to do this is to pass the zip code as an argument to the address func
tion. The zip code can be entered as an integer (27302 or 273021234 for the Zip+4),
or as a string if you wish to use the dash (-) in the Zip+4 format.
Examples:
address (27302) // Regular Zip Code As Integer
{
Kevin McHugh
4671 Mebane Rogers Road.
} print;
address ("27302") // Regular Zip Code As A String
{
...
};
address (273021234) // Zip+4 Format As An Integer
{
...
};
address ("27302-1234") // Zip+4 Format As A String
{
...
};
Using the Postnet feature is purely optional. If you do not want the bar code
printed then do not supply the Zip code between the parenthesis like so:
address ( )
{
Kevin McHugh ...
};
4. The Data Block Functions
The data blocks which we discussed above are useless without some functions which
tell the compiler what to do with them. Each data block may have one function or
none at all. If a data block doesn't have its own function then it will inherit the
function from the block before it. Here are a list of functions:
print
hold
copies
exit
The function to call is placed after the right brace and before the semi-colon of its
data block. The function will then perform its operations on the data block it is
linked to.
PRINT
Example: print
The print command simply transfers the data block over to the print spool where it
is formatted and then output according to all set variables.
HOLD
Example: hold
The hold function clears the data block buffer and returns control over to the com
piler without formatting the block or printing it. This is handy if you have a mail
ing list and you are cutting down on expenses. You can put someone's address on
hold and keep it in the list without having it printed. If a data block is on hold it is
not charged a postage fee (see Section 1 "POSTAGE").
COPIES
Example: copies( number_of_copies )
The copies function unlike the others takes an argument. The argument is an inte
ger and is the number of copies the compiler should make of the current data block.
Copies will simply continue to call the print function until the compiler has output
ted the number_of_copies requested. This function is handy for printing out mul
tiple copies of messages on the backs of postcards.
EXIT
Example: exit
The exit function calls the print routine on the current data block and then termi
nates compilation. This is used if you only need to print out a certain portion of the
mailing list. Using the exit function frees all memory and resources just like a con
ventional exit.
Here is an example of each function at work:
address ( )
{
Mike Smith
123 My Street
This Town, USA
} print;
This data block will be nicely formatted and then printed to the output file or de
vice. Note that if the data block doesn't contain any text at all then the compiler
will issue an error message.
address ( )
{
Bill Gates
Microsoft Corp.
DOSVille, USA
} hold ;
This will not print out Bill Gates' address but it will skip it and continue on down
the list.
address ( )
{
PC User
999 Dos Street
IBM, USA
};
Notice that this block doesn't have a function. What will happen? Well this block
will not be printed but rather skipped. Why? Simple, because the last function that
was processed was the hold function so it is still in effect. Check for this when
trouble-shooting.
address ( )
{
Welcome to the monthly postcard!!!
--------------------------------------------------
Don't miss this months exciting meeting featuring the all new
toaster 4000 and GVP's new EGS 24 bit graphics card.
Also this month will feature officer elections so come prepared
to vote.
See you at the meeting!!
} copies(50);
This data block will print 50 copies of the text, neatly formatted and spaced cor
rectly.
address ( )
{
Bill Johnson
862 Main Street
Amigaville, USA 12345-6789
} exit;
This data block will print Bill's address info and then exit the program.
5. Printer Commands
The Printer function is also allowed here after all the data has been processed. A
good example here would be to possible reset your printer to its default settings so
when LL exits everything will be the same as when LL was started.
For more information on the printer command see Section 2.
6. Functions
The functions are the very last entry in the source file. They are not to be confused
with the data functions which execute on the data in each data block but these ma
nipulate the overall process of the compilation.
REPORT
Example: report( );
This function is responsible for generating a summary both financial and statistical.
Here is a sample report generated by the report function:
Report For Compilation And Processing
---------------------------------------------------------------
Filename: acug.l
Submitted At: Mon Feb 7 20:36:39 1994
Completed At: Mon Feb 7 20:36:39 1994
Compilation: 0 Seconds.
-------
Number Of Entries: 20
Entries Spooled: 22
Entries Held: 1
Postage Per Entry: $0.19
-----------------------------
TOTAL POSTAGE $4.18
End Of Report.
The report generated by the report function is output to a file in the current direc
tory called report.dat. If for some reason that file could not be created then the re
port is sent to stdout usually the terminal screen.
At the time of release no other functions have yet been implemented.
Example Code
Here is a fully functional piece of L code. The names have been changed to protect
the innocent:
/* demo.l
**
** Sample L Code
** List Of Addresses
**
** Last Updated: February 01, 1994
** Kevin McHugh
**
**
** Standard Postcard Size: 24x60 @ (6 lpi)
**
*/
#define indent = 20;
#define space = 12;
#define height = 24;
#define width = 60;
#define device = out;
#define eol = lf;
#define postage = 0.19;
#define header = ***-\d-***;
printer "\e2"; // Selects 6 lines per inch spacing.
address ( )
{
Jerry Smith
123 Main Street
New York, NY
} print;
address (27302)
{
Kevin McHugh
4671 Mebane Rogers Road
Mebane, NC 27302
} hold; // No Point In Mailing Myself A Postcard.
address ( )
{
Steven Jones
987 Teacup Ave.
Los Angeles, CA
} print;
address ( )
{
Bart Simpson
346 Nice Lane
Foxville, IL
} print;
address ( )
{
Jimmy Albert
701 Malone Rd.
Smithville, TN
} hold; // Hasn't Paid His Membership Fees This Year.
address (90210)
{
Kenneth Thomas
0101 Binary Ave.
Beverly Hills, CA 90210
} print;
/* End Of Addresses */
report(); // Generate Cost Report.
The above code segment gives a simple but effective look at how easy and versatile
the LL compiler is.
Using LL
LL can only be used from the shell or from the Execute command under workbench.
The format for LL is as follows:
LL v1.5 (C) Feb 7 1994, McHugh Data Systems
A Label Language Compiler.
Usage: ll <options> <source file>
At the present time LL only supports one option. The -c option which means to com
pile the code only but not produce any output. This is a handy feature for debugging
code. It will run as normal but no output will be produced. However, a report will
be produced if requested as it is not part of the formatted output of LL. Example:
Shell> ll -c demo.l
Compile demo.l only. Don't produce output.
Shell> ll demo.l
Compile and produce output based on the file demo.l
Just issuing the LL command by itself will bring up the template.
There are multiple versions of LL in the archive:
LL LL for 68000 Amigas
LL020 LL for 68020, 68030, 68040 Amigas
LL020881 LL for 68020 or better and 68881, 68882 Math Coprocessors.
Just copy the appropriate executable to C:ll and you're all installed.
Registering LL
LL is freeware but I would appreciate it if you would drop me a line and let me
know you are using it; that way I will know whether to publicly release future up
dates and type all this documentation.
Incase you are reading all these docs in text then you may not know that there is a
handsomely bound professional 20 page printed manual which is included in the ar
chive as manual.ps but can be obtained from me by sending cash or money order for
$10 US.
As mentioned in the disclosure you can obtain the source code for LL. If you wish
to have the source code then send cash or money order in US dollars for $12 and I
will mail you the complete source and latest executables. Add $8 for the manual.
Technical Info About LL
LL consists of a top-down one pass parser which is responsible for all syntactical
and grammatical findings. The parser is fed a token from the lexicographical scan
ner which dynamically scans the file and can maneuver bidirectionally.
The scanner was hand written in C rather than using a parser generator such as
lex, or flex. The main reason was for speed and grace and the code size was reduced
from around 17k to 7k. The parser was also written in C instead of using yacc or
bison for similar reasons. The governing reason was that I wanted some practise at
optimizing the compile time. As of yet I have not found a file that takes over 2 sec
onds to compile on my 68030 machine.
Error generation and attempted correction is handled by a subset of the parser in
order to continue after minor mistakes like missing = or ; 's etc... Error traps also
catch illegal type assignments such as string to integer or float. Such an error will
cause a FATAL signal and the compiler will close down as it assumes you will want
to edit your code.
When the compiler exits, either normally or otherwise the atexit() function is called.
This flushes all I/O and releases file descriptors on all open files and devices. All in
use memory is cleaned and then put back on the heap so that your other programs
will not be in need for those precious bytes.
If this tickles your fancy consider ordering the source code so you can improve or
just learn from it.
Future Improvements
* More buffered stream I/O.
* User defined variables.
* Better compiler intelligence and correction.
* Multiple source files.
* Ability to #include text into data blocks.
* Operands ( + - / * )
* More global functions.
* More embedded escape codes.
* Faster, faster, faster.....
Acknowledgements
Editor: Cygnus-Ed Professional Release 3.5
Compiler: Manx/Aztec C Developer v5.2a
Documentation: WordPerfect v4.2 Amiga
PostNet: Chris Laforet Software
History
Version Descripion
1.0 Quick ugly label printer. Used text file for address information
seperated by blank spaces. All paper sizes hard coded.
1.1 Changed hard coded paper sizes to #defines for multiple documents.
1.2 Scrapped the whole idea and re-wrote with an intelligent text
processor in mind.
1.3 First working version with a seperate token scanner (Lex).
1.4 Deleted all Lex code and hand wrote the scanner from scratch.
1.5 New revised version of the scanner using character based I/O
and tokens. Also included seperate parser for language grammar.
1.6 Added variables and Data functions to perform other than printing
abilities.
1.7 Added ability to support external functions in the language and
coded a function to generate statistical reports.
1.8 Added feature for issuing flags on the command line. Only one
exists to date (-c compile only.)
1.9 Postnet Bar Coding was added and yet another change to the
grammar to incorporate this into the address function.
2.0 First public release of LL and first revision of user documentation.